package za.org.jcicada.datastore.impl;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Properties;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import za.org.jcicada.cfgmngr.ISystemSubject;
import za.org.jcicada.cfgmngr.SystemSetType;
import za.org.jcicada.cfgmngr.impl.SystemSubjectProxy;
import za.org.jcicada.confss.impl.ConfSS;
import za.org.jcicada.genss.ServiceURN;
import za.org.jcicada.genss.SystemURN;
import za.org.jcicada.genss.messages.Result;
import za.org.jcicada.genss.messages.SuccessCode;
import za.org.jcicada.genss.sensor.ISensorSubject;
import za.org.jcicada.genss.sensor.SensorURN;
import za.org.jcicada.genss.sensor.impl.Sensor;
import za.org.jcicada.genss.sensor.impl.SensorSubjectProxy;

public class DataStore extends ConfSS {

	/** Logger object used for logging messages. */
	private static final Log logger = LogFactory.getLog(DataStore.class);

	/** Dynamic configuration object for this class, contents from CfgMngr. */
	private DataStoreDynamicConfiguration dataStoreDynamic = new DataStoreDynamicConfiguration();
	
	/** Service URN for the datastore server */
	private ServiceURN datastoreURN;
	
	public interface ICallback {
		void setSystemSubject(ISystemSubject systemSubject);
		
		void addSensorSubject(ServiceURN serviceURN, ISensorSubject sensorSubject);
	}
	
	/** Model coordinates work */
	private Model model;
	
	/** Implements IDataStore and adaptor pattern to underlying data store implementation */
	private DataStoreServerAbstract dataStoreServer;
	
	/**
	 * Constructor
	 * 
	 * @param systemURN
	 *            the name of this device proxy object
	 * @param uriCfgMngrLocation
	 *            the location of the CfgMngr
	 */
	public DataStore(SystemURN systemURN, URI uriCfgMngrLocation) throws URISyntaxException {
		super(systemURN, uriCfgMngrLocation);
		datastoreURN = new ServiceURN(systemURN, "datastore");
	}

	/**
	 * Do base class initialization then create model.
	 */
	@Override
	protected void duringInitialize() throws Exception {
		super.duringInitialize();
		model = new Model(getConfigurationServer(), this, getTimer());
	}

	/**
	 * Shutdown the model then stops the ConfSS base object.
	 */
	@Override
	protected void duringShutdown() throws Exception {
		model.shutdown();
		super.duringShutdown();
	}
	
	@Override
	protected void addSensors() throws URISyntaxException {
		super.addSensors();
		for (Sensor sensor : model.getSensors()) {
			addSensor(getSystemURN(), sensor);
		}
	}

	@Override
	public void replyGetConfiguration(Result result, Object configuration) {
		super.replyGetConfiguration(result, configuration);
		dataStoreDynamic.loadProperties((Properties) configuration);
		try {
			dataStoreServer = dataStoreDynamic.getDataStoreServer();
		} catch (Exception e) {
			logger.error(e);
		}
		
		try {
			internalSetupAcceptors(dataStoreDynamic.datastoreURLs, new DataStoreAcceptListener(dataStoreServer), datastoreURN);
		} catch (Exception e1) {
			logger.error(e1);
		}
		// trigger model to attach to relevant systems and sensors
		try {
			model.initialize(dataStoreServer, dataStoreDynamic);
		} catch (URISyntaxException e) {
			logger.error(e);
		}
	}

	public void replyLocateService(Result result, ServiceURN serviceURN, URI locationURI) {
		logger.info(String.format("Located %s at %s", serviceURN, locationURI));
		if (result.getCode() == SuccessCode.COMPLETE_SUCCESS) {
			if (serviceURN.getInterface().equals("systems")) {
				ISystemSubject systemSubject = new SystemSubjectProxy(locationURI);
				model.setSystemSubject(systemSubject);
			}
			if (serviceURN.getInterface().equals(SensorURN.URN_SERVICE_SENSORS)) {
				ISensorSubject sensorSubject = new SensorSubjectProxy(locationURI);
				model.addSensorSubject(serviceURN, sensorSubject);
			}
		}
	}

	public void replySensorSet(Result result, SystemURN systemURN, Set<SensorURN> sensorURNs) {
	}

	public void replySystemSet(Result result, SystemSetType type, Set<SystemURN> systemURNs) {
	}

	/**
	 * Main function takes no arguments. A cfgmngr knows what it subsystemURI
	 * will be since there can be only one!
	 * 
	 * @param args
	 *            the command line arguments
	 */
	public static void main(String args[]) {
		String[] confssArgs = { DataStore.class.getCanonicalName(), args[0], args[1] };
		ConfSS.main(confssArgs);
	}

}
